 /*
 *Copyright (c) 2013-2013, yinqiwen <yinqiwen@gmail.com>
 *All rights reserved.
 * 
 *Redistribution and use in source and binary forms, with or without
 *modification, are permitted provided that the following conditions are met:
 * 
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of Redis nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 * 
 *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
 *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
 *THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef NOVA_CHANNELHELPER_HPP_
#define NOVA_CHANNELHELPER_HPP_
#include <string>
#include "common.hpp"
#include "util/exception/api_exception.hpp"
#include "util/socket_host_address.hpp"

using std::string;

namespace ardb
{
	class Channel;
	class ChannelEvent;
	class Message;
	bool fire_channel_bound(Channel* channel);

	bool fire_channel_closed(Channel* channel);

	bool fire_channel_connected(Channel* channel);

	bool fire_channel_disconnected(Channel* channel);

	bool fire_channel_interest_changed(Channel* channel);

	bool fire_channel_open(Channel* channel);

	bool fire_channel_unbound(Channel* channel);

	bool
	fire_exception_caught(Channel* channel, const APIException& cause);

	//bool fireMessageReceived(Channel* channel, Object* message, ObjectDestructor destructor=NULL);

	bool fire_channel_writable(Channel* channel);

	//bool openChannel(Channel* channel);
	//bool bindChannel(Channel* channel, Address* localAddress);
	//ChannelEvent* unbindChannel(Channel* channel);
	//bool writeChannel(Channel* channel, Object* message, ObjectDestructor destructor = NULL);

	template<typename T>
	bool write_channel(Channel* channel, T* message,
			typename Type<T>::Destructor* destructor)
	{
		MessageEvent<T> event(channel, message, destructor, false);
		return channel->GetPipeline().SendDownstream(event);
	}

	template<typename T>
	inline bool fire_message_received(Channel* channel, T* message,
			typename Type<T>::Destructor* destructor)
	{
		MessageEvent<T> event(channel, message, destructor, true);
		return channel->GetPipeline().SendUpstream(event);
	}

	template<typename T>
	inline bool fire_message_received(ChannelHandlerContext& ctx, T* message,
			typename Type<T>::Destructor* destructor)
	{
		MessageEvent<T> event(ctx.GetChannel(), message, destructor, true);
		return ctx.SendUpstream(event);
	}

	bool GetSocketRemoteAddress(Channel* ch, SocketHostAddress& address);
	bool GetSocketLocalAddress(Channel* channel, SocketHostAddress& address);

}

#endif /* CHANNELHELPER_HPP_ */
